package com.cundong.recyclerview;

import ohos.agp.components.BaseItemProvider;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.database.DataSetSubscriber;

import java.util.ArrayList;

/**
 * Created by cundong on 2015/10/9.
 * <p/>
 * BaseItemProvider with Header and Footer
 */
public class HeaderAndFooterRecyclerViewAdapter extends BaseItemProvider {
    private BaseItemProvider mInnerAdapter;

    private ArrayList<Component> mHeaderViews = new ArrayList<>();
    private ArrayList<Component> mFooterViews = new ArrayList<>();
    private boolean isReachedEndOfList = false;

    private DataSetSubscriber mDataObserver = new DataSetSubscriber() {
        @Override
        public void onChanged() {
            super.onChanged();
            mInnerAdapter.notifyDataChanged();
        }

        @Override
        public void onItemRangeChanged(int positionStart, int itemCount) {
            super.onItemRangeChanged(positionStart, itemCount);
            mInnerAdapter.notifyDataSetItemRangeChanged(positionStart + getHeaderViewsCount(), itemCount);
        }

        @Override
        public void onItemRangeInserted(int positionStart, int itemCount) {
            super.onItemRangeInserted(positionStart, itemCount);
            mInnerAdapter.notifyDataSetItemRangeChanged(positionStart + getHeaderViewsCount(), itemCount);
        }

        @Override
        public void onItemRangeRemoved(int positionStart, int itemCount) {
            super.onItemRangeRemoved(positionStart, itemCount);
            mInnerAdapter.notifyDataSetItemRangeRemoved(positionStart + getHeaderViewsCount(), itemCount);
        }
    };

    /**
     * HeaderAndFooterRecyclerViewAdapter
     *
     * @param innerAdapter innerAdapter
     */
    public HeaderAndFooterRecyclerViewAdapter(BaseItemProvider innerAdapter) {
        setAdapter(innerAdapter);
    }

    @Override
    public int getCount() {
        return getHeaderViewsCount() + getFooterViewsCount() + mInnerAdapter.getCount();
    }

    @Override
    public Object getItem(int id) {
        return mInnerAdapter.getItem(id);
    }

    @Override
    public long getItemId(int id) {
        return id;
    }

    @Override
    public Component getComponent(int position, Component component, ComponentContainer componentContainer) {
        if (isHeader(position)) {
            return getHeaderView();
        } else if (isFooter(position)) {
            return getFooterView();
        } else {
            return mInnerAdapter.getComponent(position - getHeaderViewsCount(), component, componentContainer);
        }
    }

    /**
     * setAdapter
     *
     * @param adapter adapter
     */
    public void setAdapter(BaseItemProvider adapter) {
        if (mInnerAdapter != null) {
            this.notifyDataSetItemRangeRemoved(getHeaderViewsCount(), mInnerAdapter.getCount());
            mInnerAdapter.removeDataSubscriber(mDataObserver);
        }
        this.mInnerAdapter = adapter;
        this.notifyDataSetItemRangeChanged(getHeaderViewsCount(), mInnerAdapter.getCount());
    }

    /**
     * getInnerAdapter
     *
     * @return adapter
     */
    public BaseItemProvider getInnerAdapter() {
        return mInnerAdapter;
    }

    /**
     * addHeaderView
     *
     * @param header header
     */
    public void addHeaderView(Component header) {
        if (header == null) {
            throw new IllegalArgumentException("header is null");
        }

        mHeaderViews.add(header);
        this.notifyDataSetItemRangeChanged(getHeaderViewsCount(), mInnerAdapter.getCount());
    }

    /**
     * addFooterView
     *
     * @param footer footer
     */
    public void addFooterView(Component footer) {
        if (footer == null) {
            throw new IllegalArgumentException("footer is null");
        }

        mFooterViews.add(footer);
        this.notifyDataSetItemRangeChanged(getHeaderViewsCount(), mInnerAdapter.getCount());
    }

    /**
     * getFooterView
     *
     * @return Component
     */
    public Component getFooterView() {
        return getFooterViewsCount() > 0 ? mFooterViews.get(0) : null;
    }

    /**
     * getHeaderView
     *
     * @return Component
     */
    public Component getHeaderView() {
        return getHeaderViewsCount() > 0 ? mHeaderViews.get(0) : null;
    }

    /**
     * removeHeaderView
     *
     * @param component component
     */
    public void removeHeaderView(Component component) {
        mHeaderViews.remove(component);
        this.notifyDataSetItemRangeChanged(getHeaderViewsCount(), mInnerAdapter.getCount());
    }

    /**
     * removeFooterView
     *
     * @param component component
     */
    public void removeFooterView(Component component) {
        mFooterViews.remove(component);
        this.notifyDataSetItemRangeChanged(getHeaderViewsCount(), mInnerAdapter.getCount());
    }

    /**
     * removeAllFooterView
     */
    public void removeAllFooterView() {
        mFooterViews.clear();
        isReachedEndOfList = true;
    }

    /**
     * hasReachedEnd
     *
     * @return boolean
     */
    public boolean hasReachedEnd() {
        return isReachedEndOfList;
    }

    /**
     * getHeaderViewsCount
     *
     * @return header size
     */
    public int getHeaderViewsCount() {
        return mHeaderViews.size();
    }

    /**
     * getFooterViewsCount
     *
     * @return footer size
     */
    public int getFooterViewsCount() {
        return mFooterViews.size();
    }

    /**
     * isHeader
     *
     * @param position position
     * @return boolean
     */
    public boolean isHeader(int position) {
        return getHeaderViewsCount() > 0 && position == 0;
    }

    /**
     * isFooter
     *
     * @param position position
     * @return boolean
     */
    public boolean isFooter(int position) {
        int lastPosition = getCount() - 1;
        return getFooterViewsCount() > 0 && position == lastPosition;
    }
}